﻿using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;
using vite_ef.Repositories.EntityFrameworkCore;
using vite_core.EF_Core.EFDbcontext;
using vitecore.Module;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore.Query;
using System.Linq;

namespace vite_ef.Repositories.EntityFrameworkCore
{
    //[InjectOn(Lifetime = ServiceLifetime.Scoped, Scheme = InjectScheme.OnlyInterfaces, IsT = true, Own = false)]
    public class BaseRepository<T> : IBaseRepository<T> where T : class
    {
        private readonly ViteNetDbContext context;
        private readonly DbSet<T> dbSet;

        public BaseRepository(ViteNetDbContext _context)
        {
            context = _context;
            dbSet = _context.Set<T>();
        }

        public async Task<int> SaveChangesAsync()
        {
            return await context.SaveChangesAsync();
        }


        #region 添加
        public async Task<T> AddAsync(T entity)
        {
            await dbSet.AddAsync(entity);
            await context.SaveChangesAsync();
            return entity;
        }

        public async Task<bool> AddOk(T entity)
        {
            await dbSet.AddAsync(entity);
            return await context.SaveChangesAsync() > 0;
        }
        /// <summary>
        /// 添加List
        /// </summary>
        /// <param name="entitys"></param>
        /// <returns></returns>
        public async Task<bool> AddListOk(List<T> entities)
        {
            await dbSet.AddRangeAsync(entities);
            return await context.SaveChangesAsync() > 0;
        }
        #endregion

        #region 删除
        public bool Delete(int id)
        {
            var entity = dbSet.Find(id);
            dbSet.Remove(entity);
            return context.SaveChanges() > 0;
        }

        /// <summary>
        /// 不需要调用SaveChanges
        /// </summary>
        /// <param name="whereLambda"></param>
        /// <param name="setPropertyCalls"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> BatchDeleteAsync(Expression<Func<T, bool>> whereLambda, Expression<Func<SetPropertyCalls<T>, SetPropertyCalls<T>>> setPropertyCalls, CancellationToken cancellationToken = default(CancellationToken))
        {
            return await dbSet.AsNoTracking().Where(whereLambda).ExecuteDeleteAsync(cancellationToken) > 0;
        }
        #endregion

        #region 查询
        public async Task<T> SelectByIdAsync(int id) => await dbSet.FindAsync(id);

        public async Task<T> SelectWhereAsync(Expression<Func<T, bool>> whereLambda)
        {
            //.AsNoTracking()非追踪查询
            //针对查询，在一些情况下，我们只需要返回一个只读的数据就可以，并不会对数据记录进行任何的修改。这种时候不希望Entity Framework进行不必要的状态变动跟踪，
            //可以使用Entity Framework的AsNoTracking方法来查询返回不带变动跟踪的查询结果。
            //由于是无变动跟踪，所以对返回的数据的没有进行任何修改，在SaveChanges()时，都不会提交到数据库中。
            return await dbSet.AsNoTracking().FirstOrDefaultAsync(whereLambda);
        }
        public async Task<List<T>> SelectListWhereAsync(Expression<Func<T, bool>> whereLambda)
        {
            return await dbSet.AsNoTracking().Where(whereLambda).ToListAsync();
        }

        public async Task<List<T>> SelectAllAsync()
        {
            return await dbSet.AsNoTracking().ToListAsync();
        }

        public List<T> SelectList<TOrder>(Expression<Func<T, bool>> whereLambda, bool isAsc, Expression<Func<T, TOrder>> orderbyLambda)
        {
            var list = dbSet.AsNoTracking().Where(whereLambda);
            if (isAsc)
                list = list.OrderBy<T, TOrder>(orderbyLambda);
            else
                list = list.OrderByDescending<T, TOrder>(orderbyLambda);
            return list.ToList();
        }
        //public SqlSugarPagedList<T> SelectPageList<TOrder>(PageInputBase page, Expression<Func<T, bool>> whereLambda = null, Expression<Func<T, TOrder>> orderbyLambda = null, bool isAsc = false)
        //{
        //    var list = dbSet.AsNoTracking();
        //    if (whereLambda != null)
        //    {
        //        list = list.Where(whereLambda);
        //    }
        //    if (orderbyLambda != null)
        //    {
        //        if (isAsc)
        //            list = list.OrderBy<T, TOrder>(orderbyLambda);
        //        else
        //            list = list.OrderByDescending<T, TOrder>(orderbyLambda);
        //    }
        //    SqlSugarPagedList<T> pageData = new SqlSugarPagedList<T>();
        //    pageData.PageIndex = page.PageIndex;
        //    pageData.PageSize = page.PageSize;
        //    pageData.TotalCount = list.Count();
        //    pageData.Items = list.Skip((page.PageIndex - 1) * page.PageSize).Take(page.PageSize).ToList();
        //    return pageData;
        //}

        #endregion

        #region 修改
        public async Task<T> UpdateAsync(T entity)
        {
            dbSet.Attach(entity).State = EntityState.Modified;
            await context.SaveChangesAsync();
            return entity;
        }

        public bool UpdateOk(T entity)
        {
            dbSet.Attach(entity).State = EntityState.Modified;
            return context.SaveChanges() > 0;
        }

        /// <summary>
        /// 不需要调用SaveChanges
        /// </summary>
        /// <param name="whereLambda"></param>
        /// <param name="setPropertyCalls"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> UpdateBatchOkAsync(Expression<Func<T, bool>> whereLambda, 
            Expression<Func<SetPropertyCalls<T>, SetPropertyCalls<T>>> setPropertyCalls,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            return await dbSet.AsNoTracking().Where(whereLambda).ExecuteUpdateAsync(setPropertyCalls) > 0;
        }
        #endregion

        #region 执行原生sql
        public async Task<bool> ExecSql(FormattableString Sql)
        {
            return await context.Database.ExecuteSqlInterpolatedAsync(Sql) > 0;
        }
        #endregion
    }
}